from multiprocessing import Process, Array, Value, Lock, Queue
from queue import Empty
from threading import Thread
import time
import random

f = open('test.txt', 'at', encoding='utf8')


# 进程间通信，Array和Value，可以共享值
# 推测可用于多进程需要判断或修改某个全局状态使用
def task1(i, v, a):
    time.sleep(1)
    # with v.get_lock(), a.get_lock():
    a[i] = i ** i
    v.value += i
    print('子', v.value)
    print('子', a[:])


def task2(i, l):
    # l.acquire()
    with l, f:
        time.sleep(0.1)
        print(f'测试 {i}')
        f.write(f'测试 {i}\n')
    # l.release()


def producer(q: Queue, i):
    time.sleep(random.randint(1, 3))
    q.put(f'包子{i}')
    print(f'生产了包子{i}')


def consumer(q: Queue, i):
    time.sleep(random.randint(1, 3))
    try:
        res = q.get(timeout=5)
        print(f'吃货{i} 吃了 {res}')
    except Empty:
        print(f'吃货{i}说：没有能吃的东西了！！')


if __name__ == '__main__':
    # 'i' 表示有符号整数，一共 8 位，其中 1 位符号位，7 位数据位，即 -128 ~ 127
    # https://docs.python.org/zh-cn/3/library/array.html#module-array
    array = Array('i', 4)
    value = Value('b', 123)
    p_list = []
    for x in range(4):
        p = Process(target=task1, args=(x, value, array))
        p.start()
        p_list.append(p)
    [p.join() for p in p_list]
    print('主,array', array[:])  # 主,array [1, 1, 4, 27]
    print('主,value', value.value)  # 主,value -127

    # 文件实现进程间通信
    p_list.clear()
    lock = Lock()
    for x in range(100):
        p = Process(target=task2, args=(x, lock))
        p.start()
        p_list.append(p)
    [p.join() for p in p_list]
    f.close()
    print('done')

    # 消息队列实现进程通信，生产者消费者模型
    queue = Queue(5)
    producer_list = []
    consumer_list = []
    for i in range(10):
        p = Process(target=producer, args=(queue, i))
        p.start()
        producer_list.append(p)
    for i in range(15):
        q = Process(target=consumer, args=(queue, i))
        q.start()
        consumer_list.append(q)
    [p.join() for p in producer_list]
    [q.join() for q in producer_list]
